package club.worldbang.structures.queue;

import java.io.Serializable;
import java.util.NoSuchElementException;

import club.worldbang.structures.linkedList.singleLinked.Node;

// 链式队列的实现
public class LinkedQueue<T> implements Serializable, Queue<T> {

	private static final long serialVersionUID = 6202049738420107703L;
	/**
	 * 指向队头和队尾的结点 front==null&&rear==null时,队列为空
	 */
	private Node<T> front, rear;
	private int size;
	/**
	 * 用于控制最大容量,默认128,offer方法使用
	 */
	private int maxSize = 128;

	public LinkedQueue() {
		// 初始化队列
		this.front = this.rear = null;
	}

	@Override
	public int size() {
		return size;
	}

	@Override
	public boolean isEmpty() {
		return front == null && rear == null;
	}

	// 入队
	@Override
	public boolean add(T data) {
		Node<T> q = new Node<>(data, null);
		if (this.front == null) {// 空队列插入
			this.front = q;
		} else {// 非空队列,尾部插入
			this.rear.next = q;
		}
		this.rear = q;
		size++;
		return true;
	}

	@Override
	public boolean offer(T data) {
		if (data == null)
			throw new NullPointerException("The data can\'t be null");
		if (size >= maxSize)
			throw new IllegalArgumentException("The capacity of LinkedQueue has reached its maxSize:128");

		Node<T> q = new Node<>(data, null);
		if (this.front == null) {// 空队列插入
			this.front = q;
		} else {// 非空队列,尾部插入
			this.rear.next = q;
		}
		this.rear = q;
		size++;
		return false;
	}

	@Override
	public T peek() {
		return this.isEmpty() ? null : this.front.data;
	}

	@Override
	public T element() {
		if (isEmpty()) {
			throw new NoSuchElementException("The LinkedQueue is empty");
		}
		return this.front.data;
	}

	@Override
	public T poll() {
		if (this.isEmpty())
			return null;
		T x = this.front.data;
		this.front = this.front.next;
		if (this.front == null)
			this.rear = null;
		size--;
		return x;
	}

	@Override
	public T remove() {
		if (isEmpty()) {
			throw new NoSuchElementException("The LinkedQueue is empty");
		}
		T x = this.front.data;
		this.front = this.front.next;
		if (this.front == null)
			this.rear = null;
		size--;
		return x;
	}

	@Override
	public void clearQueue() {
		this.front = this.rear = null;
		size = 0;
	}

}
